import pandas as pd
import numpy as np
import random
from datetime import datetime, timedelta
import os
from config import dummy_data_dir

# 设置随机种子保证结果可复现
np.random.seed(42)
random.seed(42)

# 1. 基础数据准备
# 运营商号段分配 (移动/电信/联通)
operator_prefix = {
    '移动': ['134', '135', '136', '137', '138', '139', '147', '150', '151', '152', '157', '158', '159', '178', '182', '183', '184', '187', '188', '198'],
    '电信': ['133', '149', '153', '173', '177', '180', '181', '189', '199'],
    '联通': ['130', '131', '132', '145', '155', '156', '166', '171', '175', '176', '185', '186']
}

# 套餐信息 (按运营商分类)
package_info = {
    '移动': [
        {'name': '移动大王卡', 'data': 30, 'call': 100, 'fee': 29},
        {'name': '全球通尊享套餐', 'data': 50, 'call': 500, 'fee': 128},
        {'name': '神州行畅聊卡', 'data': 5, 'call': 300, 'fee': 19},
        {'name': '5G智享套餐', 'data': 100, 'call': 1000, 'fee': 199},
        {'name': '和飞享套餐', 'data': 20, 'call': 200, 'fee': 39}
    ],
    '电信': [
        {'name': '电信无忧卡', 'data': 10, 'call': 50, 'fee': 19},
        {'name': '十全十美套餐', 'data': 40, 'call': 400, 'fee': 99},
        {'name': '天翼畅享套餐', 'data': 60, 'call': 800, 'fee': 129},
        {'name': '5G融合套餐', 'data': 120, 'call': 1500, 'fee': 199},
        {'name': '青年一派卡', 'data': 30, 'call': 200, 'fee': 29}
    ],
    '联通': [
        {'name': '联通大王卡', 'data': 40, 'call': 0, 'fee': 19},
        {'name': '冰淇淋套餐', 'data': 100, 'call': 1000, 'fee': 129},
        {'name': '沃派套餐', 'data': 20, 'call': 300, 'fee': 39},
        {'name': '5G畅爽套餐', 'data': 80, 'call': 500, 'fee': 99},
        {'name': '校园套餐', 'data': 30, 'call': 200, 'fee': 29}
    ]
}

# 北京市各区分布（按人口密度加权）
beijing_districts = {
    '朝阳区': 0.22,    # 人口最多的区
    '海淀区': 0.18,    # 高校和科技企业集中
    '丰台区': 0.12,    # 交通枢纽和住宅区
    '大兴区': 0.10,    # 近年发展迅速的新区
    '通州区': 0.09,    # 城市副中心
    '昌平区': 0.08,    # 回龙观、天通苑等大型社区
    '西城区': 0.07,    # 市中心，商业和政务区
    '东城区': 0.06,    # 市中心，历史文化区
    '房山区': 0.04,    # 郊区
    '石景山区': 0.03,  # 首钢搬迁后发展区域
    '顺义区': 0.03,    # 机场周边
    '怀柔区': 0.02,    # 远郊区
    '门头沟区': 0.01,  # 远郊区
    '平谷区': 0.01,    # 远郊区
    '密云区': 0.01,    # 远郊区
    '延庆区': 0.01     # 远郊区
}

# 将权重转换为列表用于随机选择
districts = list(beijing_districts.keys())
weights = list(beijing_districts.values())

# 2. 生成用户基础信息
# 用户ID列表
user_ids = [f"U{str(i).zfill(5)}" for i in range(1, 3001)]

# 用户号码数量分配
user_phone_counts = []
for i in range(3000):
    if i < 2340:  # 78%用户有1个号码
        user_phone_counts.append(1)
    elif i < 2340 + 570:  # 19%用户有2个号码
        user_phone_counts.append(2)
    else:  # 3%用户有3个号码
        user_phone_counts.append(3)

# 3. 生成手机号及运营商信息
def generate_phone_number(operator):
    """生成指定运营商的手机号"""
    prefix = random.choice(operator_prefix[operator])
    # 生成后8位数字
    suffix = ''.join([str(random.randint(0, 9)) for _ in range(8)])
    return prefix + suffix

def assign_operator(phone_count, index):
    """为指定用户分配运营商组合"""
    # 单卡用户
    if phone_count == 1:
        if index < 1357:
            return ['移动']
        elif index < 1357 + 538:
            return ['电信']
        else:
            return ['联通']
    
    # 双卡用户
    elif phone_count == 2:
        if index < 132:
            return ['移动', '移动']
        elif index < 132 + 52:
            return ['电信', '电信']
        elif index < 132 + 52 + 44:
            return ['联通', '联通']
        elif index < 132 + 52 + 44 + 159:
            return ['移动', '电信']
        elif index < 132 + 52 + 44 + 159 + 131:
            return ['移动', '联通']
        else:
            return ['电信', '联通']
    
    # 三卡用户
    else:  # phone_count == 3
        if index < 5:
            return ['移动', '移动', '移动']
        elif index < 5 + 2:
            return ['电信', '电信', '电信']
        elif index < 5 + 2 + 2:
            return ['联通', '联通', '联通']
        elif index < 5 + 2 + 2 + 14:
            return ['移动', '移动', '电信']
        elif index < 5 + 2 + 2 + 14 + 12:
            return ['移动', '移动', '联通']
        elif index < 5 + 2 + 2 + 14 + 12 + 8:
            return ['电信', '电信', '移动']
        elif index < 5 + 2 + 2 + 14 + 12 + 8 + 2:
            return ['电信', '电信', '联通']
        elif index < 5 + 2 + 2 + 14 + 12 + 8 + 2 + 6:
            return ['联通', '联通', '移动']
        elif index < 5 + 2 + 2 + 14 + 12 + 8 + 2 + 6 + 3:
            return ['联通', '联通', '电信']
        else:
            return ['移动', '电信', '联通']

# 4. 生成入网信息表
data = []
single_index = 0
double_index = 0
triple_index = 0

# 携号转网概率矩阵（行:当前运营商, 列:转网后运营商）
portability_matrix = {
    '移动': {'电信': 0.5, '联通': 0.5},
    '电信': { '移动': 0.75, '联通': 0.25},
    '联通': {'移动': 0.68, '电信': 0.32}
}

for user_idx, user_id in enumerate(user_ids):
    phone_count = user_phone_counts[user_idx]
    
    # 获取该用户的运营商组合（初始运营商）
    if phone_count == 1:
        initial_operators = assign_operator(1, single_index)
        single_index += 1
    elif phone_count == 2:
        initial_operators = assign_operator(2, double_index)
        double_index += 1
    else:
        initial_operators = assign_operator(3, triple_index)
        triple_index += 1
    
    # 为该用户的所有号码选择归属地 (75%概率同一区，25%概率不同区)
    if random.random() < 0.75:
        # 同一区
        district = random.choices(districts, weights=weights, k=1)[0]
        locations = [district] * phone_count
    else:
        # 不同区
        locations = random.choices(districts, weights=weights, k=phone_count)
    
    # 为该用户的所有号码生成入网时间 (80%概率同一天入网，20%概率不同时间入网)
    if random.random() < 0.8:
        # 同一入网时间
        # 入网时间范围：2010-2023年，重点在2015-2020年
        year = random.choices(
            [2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025],
            weights=[0.02, 0.03, 0.05, 0.07, 0.10, 0.15, 0.15, 0.15, 0.12, 0.08, 0.04, 0.02, 0.01, 0.01],
            k=1
        )[0]
        month = random.randint(1, 12)
        day = random.randint(1, 28)  # 避免2月29日问题
        start_date = datetime(year, month, day)
        net_dates = [start_date] * phone_count
    else:
        # 不同入网时间（间隔1-24个月）
        net_dates = []
        base_date = datetime(2010, 1, 1) + timedelta(days=random.randint(0, 5475))
        for i in range(phone_count):
            # 每个号码入网时间间隔1-24个月
            offset = random.randint(0, 730)  # 0-730天（约2年）
            net_dates.append(base_date + timedelta(days=offset))
    
    # 为每个号码生成数据
    for phone_idx in range(phone_count):
        initial_operator = initial_operators[phone_idx]
        district = locations[phone_idx]
        net_date = net_dates[phone_idx]
        # 生成手机号（基于初始运营商）
        phone_number = generate_phone_number(initial_operator)

         # 确定当前运营商和携号转网状态
        # 10%的概率号码发生过携号转网
        if random.random() < 0.10:
            # 根据转网概率矩阵确定当前运营商
            current_operator = random.choices(
                list(portability_matrix[initial_operator].keys()),
                weights=list(portability_matrix[initial_operator].values()),
                k=1
            )[0]
            portability_status = '是'
            
            # 转网后选择新套餐（通常是更优惠的转网专享套餐）
            package = random.choice(package_info[current_operator])
        
        else:
            current_operator = initial_operator
            portability_status = '否'
            # 选择初始套餐
            package = random.choice(package_info[initial_operator])
        
        # 生成离网时间 (8%概率有离网时间)
        if random.random() < 0.08:
            # 在入网时间后1天到5年之间随机，高峰在1-2年
            duration = random.choices(
                [30, 60, 90, 180, 365, 730, 1095, 1460, 1825],
                weights=[0.05, 0.10, 0.15, 0.20, 0.25, 0.15, 0.05, 0.03, 0.02],
                k=1
            )[0]
            end_date = net_date + timedelta(days=duration)
        else:
            end_date = None
        
        # 添加到数据表
        data.append({
            'User ID': user_id,
            'Mobile Number': phone_number,
            'Activation Date': net_date.strftime('%Y-%m-%d'),
            'Plan Name': package['name'],
            'Data Allowance (GB)': package['data'],
            'Free Call Minutes': package['call'],
            'Monthly Fee (RMB)': package['fee'],
            'Termination Date': end_date.strftime('%Y-%m-%d') if end_date else '',
            'Registered Location': f"北京市{district}",
            'Current Operator': current_operator,
            'Portability Status': portability_status
        })

# 5. 创建DataFrame并保存为Excel  
df = pd.DataFrame(data)
output_file = os.path.join(dummy_data_dir, '用户入网信息表.csv')
df.to_csv(output_file, index=False, encoding='utf-8-sig')

# 6. 统计信息
print(f"数据生成完成，共{len(df)}条记录，已保存至: {os.path.abspath(output_file)}")
print("\n北京市各区分布统计:")
print(df['Registered Location'].value_counts(normalize=True).sort_index())

print("\n运营商分布统计:")
print("初始运营商分布:")
initial_operator_counts = pd.Series([op for sublist in [assign_operator(count, i) 
                                                      for i, count in enumerate(user_phone_counts)] 
                                    for op in sublist]).value_counts(normalize=True)
print(initial_operator_counts)

print("\n当前运营商分布:")
print(df['Current Operator'].value_counts(normalize=True))

